home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Snippets / Printing / Print clipped offscreen / Offscreen Region.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-14  |  11.5 KB  |  400 lines  |  [TEXT/CWIE]

  1. /*
  2. **  Apple Macintosh Developer Technical Support
  3. **
  4. **  Sample showing how to print clipped offscreens.
  5. **
  6. **  by Tim Carroll and Ingrid Kelly, Apple Developer Technical Support
  7. **
  8. **  File:   Offscreen Region.c
  9. **
  10. **  Copyright ©1996 Apple Computer, Inc.
  11. **  All rights reserved.
  12. **
  13. **    2/94    v. 1.0    Shipped as 'Offscreen region MaskRgn' sample.
  14. **    11/96    v. 2.0    Rewritten as 'Print clipped offscreen' to fix 
  15. **                    problems printing to PostScript printers (changed
  16. **                    maskRgn to clipping the region before sending to the
  17. **                    printing port since PS printers don't support maskRgn)
  18. **
  19. **  You may incorporate this sample code into your applications without
  20. **  restriction, though the sample code has been provided "AS IS" and the
  21. **  responsibility for its operation is 100% yours.  However, what you are
  22. **  not permitted to do is to redistribute the source as "Apple Sample
  23. **  Code" after having made changes. If you're going to re-distribute the
  24. **  source, we require that you make it clear in the source that the code
  25. **  was descended from Apple Sample Code, but that you've made changes.
  26. */
  27.  
  28. /**------------------------------------------------------------------------------------** 
  29.     Print clipped offscreen:  Takes a text string, turns it into a region and
  30.     copies a clipped bitmap (just a pattern in this case, but it could be 
  31.     anything) to the printing grafPort.  The effect is patterned text here, 
  32.     but any image could be showing through the text.
  33.     
  34.     You can also see the clipped image on the screen by turning on DrawStuffToScreen.
  35.     Do this with qdToScreen below.
  36.  
  37.     This sample is a rewrite of the 'Offscreen region MaskRgn' sample.
  38.  
  39.  **-----------------------------------------------------------------------------------**/
  40.  
  41. /*************************************************************************************
  42. #
  43. #    CONDITIONALS
  44. #
  45. #    There are a number of conditionals used to control exactly how the code runs.
  46. #
  47. #
  48. #    qDebugging  -- Whether or not additional debugging code should be inserted.  With this
  49. #   turned on, most errors will DebugStr almost immediately and return errors as the error
  50. #   propagates up the calling chain.  This is slower, but if you've found a weird bug,
  51. #   this is the fastest way to replicate it.
  52. #
  53. #    qdToScreen -- if this is set to 1, we draw to the screen instead of to the printer.
  54. #
  55. *************************************************************************************/
  56.  
  57. #define qDebugging 1
  58. #define qdToScreen 0
  59.  
  60.  
  61. /*********************************************************************************
  62. #    ERROR HANDLING MACROS
  63. #
  64. #    These macros can be used to implement nice error handling within a function.
  65. #    Essentially, all errors jump to an error handler at the end of the function, which
  66. #    should cleanup  any leftovers and return the appropriate error result.
  67. #
  68. #    Note that the error handlers take a message string.  This should be a good
  69. #    indication of the actual error, and it will appear when debugging is turned on.
  70. #
  71. #    Note that any additional sanity checking code can be added to any function by using
  72. #
  73.     
  74.     #if qDebugging
  75.           // do additional sanity checking here.
  76.     #endif
  77. #
  78. #    For example, this could be used to check the internal validity of an object before
  79. #    taking an action.
  80. #    
  81. *********************************************************************************/
  82.  
  83. #ifndef qDebugging
  84.     #define qDebugging 0
  85. #endif
  86.  
  87. #if qDebugging
  88.     #define SIGNAL_ERROR(msg)        {DebugStr(msg); goto error;}
  89. #else
  90.     #define SIGNAL_ERROR(msg)        {goto error;}
  91. #endif
  92.  
  93. #define FAIL_NIL(y,msg)            if (y == NULL) SIGNAL_ERROR(msg)
  94. #define FAIL_OSERR(y,msg)        if (y != noErr) SIGNAL_ERROR(msg)
  95. #define FAIL_FALSE(y,msg)        if (!y) SIGNAL_ERROR(msg)
  96.  
  97.  
  98.  
  99. #include <Printing.h>
  100. #include <QDOffscreen.h>
  101.  
  102. void         main (void);
  103. OSStatus    PrintStuff (void);
  104. OSStatus    DrawStuff (Rect theWorld);
  105. OSStatus    PrepareOffScreens(void);
  106. OSStatus    KillOffscreens(void);
  107. OSStatus    DrawStuffToScreen(void);
  108.  
  109. /*------ globals --------------------------------------------------------------------------*/
  110.  
  111. GWorldPtr    gMaskOffscreen = NULL, gImageOffscreen = NULL;
  112. RgnHandle    gMaskRegion = NULL;
  113. Rect        gBoundsRect;
  114.  
  115. /*------ main ----------------------------------------------------------------------------*/
  116. //    All main does is the standard mac init, followed by initializing the offscreens
  117. //    and printing.
  118. /*----------------------------------------------------------------------------------------*/
  119.  
  120. void main(void)
  121. {
  122.     OSStatus theErr = noErr;
  123.     
  124.     InitGraf(&qd.thePort);
  125.     InitFonts();
  126.     InitWindows();
  127.     InitMenus();
  128.     TEInit();
  129.     InitDialogs(nil);
  130.     InitCursor();
  131.  
  132.     theErr = PrepareOffScreens();
  133.     FAIL_OSERR (theErr, "\pError: Failed to prepare the offscreen environment")
  134.     
  135.     #if qdToScreen        
  136.         DrawStuffToScreen();
  137.     while (!Button());
  138.     #else
  139.         PrintStuff ();
  140.     #endif
  141.     
  142. error:
  143.     theErr = KillOffscreens();
  144.     
  145. } /* main */
  146.  
  147.  
  148. /*------ PrepareOffScreens ---------------------------------------------------------------*/
  149. //    PrepareOffScreens sets up the GWorlds and does the actual text clipping.
  150. /*----------------------------------------------------------------------------------------*/
  151.  
  152. OSStatus PrepareOffScreens()
  153. {
  154.     OSStatus theErr = noErr;
  155.     CGrafPtr savePort;
  156.     GDHandle saveDevice;
  157.     short fontNum;
  158.     PixPatHandle image = NULL;
  159.     PixMapHandle thePix = NULL;
  160.     
  161.     SetRect(&gBoundsRect,0,0,700,700);
  162.     GetGWorld(&savePort,&saveDevice);
  163.     
  164.     /* Create the offscreen mask */
  165.     
  166.     theErr = NewGWorld(&gMaskOffscreen, 1, &gBoundsRect, NULL, NULL, 0);
  167.     FAIL_OSERR (theErr, "\pError: Failed to create mask GWorld")
  168.     FAIL_NIL (gMaskOffscreen, "\pError: Failed to create mask GWorld")
  169.     
  170.     thePix = GetGWorldPixMap (gMaskOffscreen);
  171.     FAIL_NIL (thePix, "\pError: Failed to retrieve mask pixmap")
  172.     FAIL_FALSE (LockPixels(thePix), "\pError: Failed to lock the mask pixmap")
  173.     
  174.     SetGWorld(gMaskOffscreen,NULL);
  175.     ClipRect(&gBoundsRect);
  176.     
  177.     ForeColor(blackColor);
  178.     EraseRect(&gBoundsRect);
  179.     GetFNum("\pTimes",&fontNum);
  180.     TextFont(fontNum);
  181.     TextFace(bold);
  182.     TextSize(60);
  183.     MoveTo(10,100);
  184.     DrawString("\pHere’s our string test");
  185.     
  186.     SetGWorld (savePort,saveDevice);
  187.     
  188.     /* OK, the mask pixmap now has our string in it.  Let's make a region from it. */
  189.  
  190.     gMaskRegion = NewRgn();
  191.     theErr = QDError();
  192.     FAIL_OSERR (theErr, "\pError: Failed to create the mask region")
  193.     FAIL_NIL (gMaskRegion,"\pError: Failed to create the mask region")
  194.     
  195.     theErr = BitMapToRegion(gMaskRegion,&((GrafPtr)gMaskOffscreen)->portBits);
  196.     FAIL_OSERR (theErr, "\pError: Failed to convert the mask to a region")
  197.     
  198.     UnlockPixels (thePix);
  199.     
  200.     
  201.     /* Build the offscreen pixmap that we'll draw to the printer */
  202.     
  203.     theErr = NewGWorld(&gImageOffscreen, 8, &gBoundsRect, NULL, NULL, 0);
  204.     FAIL_OSERR (theErr, "\pError: Failed to create image GWorld")
  205.     FAIL_NIL (gImageOffscreen, "\pError: Failed to create image GWorld")
  206.     
  207.     thePix = GetGWorldPixMap (gImageOffscreen);
  208.     FAIL_NIL (thePix, "\pError: Failed to retrieve image pixmap")
  209.     FAIL_FALSE (LockPixels(thePix), "\pError: Failed to lock the image pixmap")
  210.     
  211.     /* We erase the image, then we use the mask clipping region and draw a color
  212.        pattern to the pixmap */ 
  213.     
  214.     image = GetPixPat(16);
  215.     FAIL_NIL (image, "\pError: Failed to load the pixel pat")
  216.     
  217.     SetGWorld(gImageOffscreen,NULL);
  218.     ClipRect (&gBoundsRect);
  219.     EraseRect (&gBoundsRect);
  220.     
  221.     SetClip(gMaskRegion);
  222.     
  223.     FillCRect(&gBoundsRect, image);
  224.     
  225.     // restore the clip rect
  226.     ClipRect (&gBoundsRect);
  227.     UnlockPixels(thePix);
  228.     
  229.     // Cleanup and return noErr;
  230.     goto cleanup;
  231.     
  232. error:
  233.     if (theErr == noErr)
  234.         theErr = paramErr;
  235.     
  236. cleanup:
  237.     SetGWorld (savePort, saveDevice);
  238.     if (image != NULL)
  239.         DisposePixPat(image);
  240.     
  241.     return theErr;
  242. }
  243.  
  244. /*------ DrawStuff -----------------------------------------------------------------------*/
  245. // DrawStuff CopyBits from the offscreen into the printer/window port.
  246. /*----------------------------------------------------------------------------------------*/
  247.  
  248. OSStatus DrawStuff (Rect theRect)
  249. {
  250.     OSStatus        theErr = noErr;
  251.     GrafPtr            currentPort;
  252.     PixMapHandle     offscreenPix;
  253.  
  254.     /* Here's where we use CopyBits to copy from gImageOffscreen to the printer/window port */
  255.     
  256.     GetPort(¤tPort);
  257.     
  258.     offscreenPix = GetGWorldPixMap(gImageOffscreen);
  259.     FAIL_NIL (offscreenPix, "\pError: Failed to retrieve image pixmap")
  260.     FAIL_FALSE (LockPixels(offscreenPix), "\pError: Failed to lock the image pixmap")
  261.  
  262.     CopyBits((BitMap*)*offscreenPix,
  263.              &(currentPort)->portBits,
  264.              &gBoundsRect, &gBoundsRect, srcCopy, NULL);
  265.              
  266.     UnlockPixels(offscreenPix);
  267.  
  268.     goto cleanup;
  269.     
  270. error:
  271.     if (theErr == noErr)
  272.         theErr = paramErr;
  273. cleanup:
  274.     return theErr;
  275. }  /* DrawStuff */
  276.  
  277. /*------ PrintStuff ----------------------------------------------------------------------*/
  278. // PrintStuff performs the generic printing calls for printing to the Macintosh Printing
  279. // Manager.
  280. // Sets the current port to the printer port.
  281. /*----------------------------------------------------------------------------------------*/
  282.  
  283. OSStatus PrintStuff ()
  284. {
  285.     OSStatus    theErr = noErr;
  286.     GrafPtr        oldPort;
  287.     THPrint        thePrRecHdl;
  288.     TPPrPort    thePrPort;
  289.     TPrStatus    theStatus;
  290.  
  291.     GetPort(&oldPort);
  292.     
  293.     thePrRecHdl = (THPrint)  NewHandle (sizeof (TPrint));
  294.     theErr = MemError();
  295.     FAIL_OSERR( theErr, "\pError: Failed to allocate a TPrint record")
  296.     FAIL_NIL (thePrRecHdl, "\pError: Failed to allocate a TPrint record")
  297.     
  298.      PrOpen(); //The PrOpen procedure prepares the current printer driver for use. 
  299.      theErr = PrError();
  300.      FAIL_OSERR (theErr, "\pError: Failed to open the printer driver")
  301.      
  302.     PrintDefault(thePrRecHdl);
  303.     PrValidate(thePrRecHdl);
  304.     theErr = PrError();
  305.      FAIL_OSERR (theErr, "\pError: Failed to create a valid print record")
  306.  
  307.     if (! PrStlDialog(thePrRecHdl)) 
  308.         goto cleanup; // user cancelled
  309.               
  310.     if (! PrJobDialog(thePrRecHdl)) 
  311.         goto cleanup; // user cancelled
  312.  
  313.     thePrPort = PrOpenDoc(thePrRecHdl, nil, nil);
  314.     theErr = PrError();
  315.     
  316.     if (theErr == noErr)
  317.     {
  318.         PrOpenPage(thePrPort, nil);
  319.          theErr = PrError();
  320.          
  321.          if (theErr == noErr)
  322.          {
  323.              // Finally, we're ready to draw!
  324.             DrawStuff ((**thePrRecHdl).prInfo.rPage);
  325.             PrClosePage(thePrPort);
  326.          }
  327.          
  328.          PrCloseDoc(thePrPort);
  329.     }
  330.     
  331.     theErr = PrError();
  332.     FAIL_OSERR (theErr, "\pError: Document failed to print")
  333.     
  334.     if ((((TPPrint)*thePrRecHdl)->prJob.bJDocLoop == bSpoolLoop))
  335.         PrPicFile(thePrRecHdl, nil, nil, nil, &theStatus);                
  336.         
  337.     goto cleanup;
  338.     
  339. error:
  340.     if (theErr == noErr)
  341.         theErr = paramErr;
  342.  
  343.     
  344. cleanup:
  345.     SetPort(oldPort);
  346.     PrClose();
  347.     if (thePrRecHdl)
  348.         DisposeHandle ((Handle) thePrRecHdl);
  349.     
  350.     return theErr;
  351. }  /* PrintStuff */
  352.  
  353. /*------ KillOffscreens  ------------------------------------------------------------------*/
  354. // KillOffscreens cleans up the offscreens.
  355. /*----------------------------------------------------------------------------------------*/
  356.  
  357. OSStatus KillOffscreens()
  358. {
  359.     if (gMaskOffscreen)
  360.         DisposeGWorld(gMaskOffscreen);
  361.     if (gImageOffscreen)
  362.         DisposeGWorld(gImageOffscreen);
  363.     if (gMaskRegion)
  364.         DisposeRgn(gMaskRegion);
  365.  
  366.     return noErr;
  367. } /* KillOffscreens */
  368.  
  369. /*------ DrawStuffToScreen  ------------------------------------------------------------------*/
  370. // DrawStuffToScreen sets up the window port.
  371. // Sets the current port to the window port.
  372. /*----------------------------------------------------------------------------------------*/
  373.  
  374. OSStatus DrawStuffToScreen(void)
  375. {
  376.     WindowRef    theWindow = NULL;
  377.     Rect        bounds = gBoundsRect;
  378.     OSStatus    theErr = noErr;
  379.     GrafPtr        savePort;
  380.     
  381.     GetPort (&savePort);
  382.     
  383.     OffsetRect (&bounds, 30,30);
  384.     theWindow = NewCWindow(NULL, &bounds, "\pFoo", true, 0, (WindowRef)-1, false, 0);
  385.     FAIL_NIL (theWindow, "\pError: Failed to create the window")
  386.  
  387.     SetPortWindowPort (theWindow);
  388.     theErr = DrawStuff(gBoundsRect);
  389.     
  390.     goto cleanup;
  391.     
  392. error:
  393.     if (theErr == noErr)
  394.         theErr = paramErr;
  395.     
  396. cleanup:
  397.     SetPort (savePort);
  398.     
  399.     return theErr;
  400. } /* DrawStuffToScreen */